package cn.anecansaitin.jep.interpreter.evaluators;

import cn.anecansaitin.jep.TokenType;
import cn.anecansaitin.jep.interpreter.Interpreter;
import cn.anecansaitin.jep.parser.ast.node.expression.Binary;
import cn.anecansaitin.jep.parser.ast.node.expression.Expression;
import cn.anecansaitin.jep.parser.ast.node.expression.Grouping;
import cn.anecansaitin.jep.parser.ast.node.expression.Ternary;
import cn.anecansaitin.jep.parser.ast.node.expression.literal.StringLiteral;
import cn.anecansaitin.jep.types.TypeInfo;

public class StringEvaluator {
    public static String evaluate(Expression expression) {
        return switch (expression) {
            case Binary binary -> binary(binary);
            case Ternary ternary -> ternary(ternary);
            case Grouping grouping -> evaluate(grouping.expression());
            case StringLiteral stringLiteral -> stringLiteral.value();
            default -> throw Interpreter.markError(expression, "未实现的运算符");
        };
    }

    private static String binary(Binary binary) {
        if (binary.operator().type() == TokenType.PLUS) {
            return switch (binary.left().resultType()) {
                case INT -> {
                    int leftValue = IntEvaluator.evaluate(binary.left());

                    if (binary.right().resultType() == TypeInfo.STRING) {
                        yield leftValue + evaluate(binary.right());
                    } else {
                        throw Interpreter.markError(binary, "无法将" + binary.operator() + "运算符用于" + binary.left().resultType() + "和" + binary.right().resultType());
                    }
                }
                case LONG -> {
                    long leftValue = LongEvaluator.evaluate(binary.left());

                    if (binary.right().resultType() == TypeInfo.STRING) {
                        yield leftValue + evaluate(binary.right());
                    } else {
                        throw Interpreter.markError(binary, "无法将" + binary.operator() + "运算符用于" + binary.left().resultType() + "和" + binary.right().resultType());
                    }
                }
                case FLOAT -> {
                    float leftValue = FloatEvaluator.evaluate(binary.left());

                    if (binary.right().resultType() == TypeInfo.STRING) {
                        yield leftValue + evaluate(binary.right());
                    } else {
                        throw Interpreter.markError(binary, "无法将" + binary.operator() + "运算符用于" + binary.left().resultType() + "和" + binary.right().resultType());
                    }
                }
                case DOUBLE -> {
                    double leftValue = DoubleEvaluator.evaluate(binary.left());

                    if (binary.right().resultType() == TypeInfo.STRING) {
                        yield leftValue + evaluate(binary.right());
                    } else {
                        throw Interpreter.markError(binary, "无法将" + binary.operator() + "运算符用于" + binary.left().resultType() + "和" + binary.right().resultType());
                    }
                }
                case CHAR -> {
                    char leftValue = CharEvaluator.evaluate(binary.left());

                    if (binary.right().resultType() == TypeInfo.STRING) {
                        yield leftValue + evaluate(binary.right());
                    } else {
                        throw Interpreter.markError(binary, "无法将" + binary.operator() + "运算符用于" + binary.left().resultType() + "和" + binary.right().resultType());
                    }
                }
                case STRING -> {
                    String leftValue = evaluate(binary.left());

                    yield switch (binary.right().resultType()) {
                        case INT ->  leftValue + IntEvaluator.evaluate(binary.right());
                        case LONG -> leftValue + LongEvaluator.evaluate(binary.right());
                        case FLOAT -> leftValue + FloatEvaluator.evaluate(binary.right());
                        case DOUBLE -> leftValue + DoubleEvaluator.evaluate(binary.right());
                        case BOOLEAN -> leftValue + BooleanEvaluator.evaluate(binary.right());
                        case CHAR -> leftValue + CharEvaluator.evaluate(binary.right());
                        case STRING -> leftValue + evaluate(binary.right());
                        default -> throw Interpreter.markError(binary, "无法将" + binary.operator() + "运算符用于" + binary.left().resultType() + "和" + binary.right().resultType());
                    };
                }
                default -> throw Interpreter.markError(binary, "无法将" + binary.operator() + "运算符用于" + binary.left().resultType() + "和" + binary.right().resultType());
            };
        } else {
            throw Interpreter.markError(binary, "无法将" + binary.operator() + "运算符用于" + binary.left().resultType() + "和" + binary.right().resultType());
        }
    }

    private static String ternary(Ternary ternary) {
        boolean condition = BooleanEvaluator.evaluate(ternary.condition());
        Expression trueExpression = ternary.trueValue();
        Expression falseExpression = ternary.falseValue();

        if (condition) {
            return switch (trueExpression.resultType()) {
                case STRING -> evaluate(trueExpression);
                default -> throw Interpreter.markError(ternary, "不支持的表达式结果类型");
            };
        } else {
            return switch (falseExpression.resultType()) {
                case STRING -> evaluate(falseExpression);
                default -> throw Interpreter.markError(ternary, "不支持的表达式结果类型");
            };
        }
    }
}
